#pragma once

#include "VariableTable.h"
#include "TokenStream.h"

namespace cal
{

class Parse
{
public:
    Parse()  = default;
    ~Parse() = default;

public:
    bool quit() const { return _quit; }
    /**
     * @brief 解析 is 流，结果输出到 os 流中
     * @param reserve_last 是否保留上一次解析的结果 (即变量表)
     */
    void parse(std::istream& is = std::cin, std::ostream& os = std::cout, bool reserve_last = false);

private:
    void           parse_command_line(TokenStream& ts, std::ostream& os);
    void           clear_mess(TokenStream& ts);
    header::Number get_value(const Identifier& id);

private:    /* parse keyword */
    /**
     * set: 'set' assignment-stmt
     */
    void parse_set(TokenStream& ts);
    /**
     * @brief assignment-stmt: variable '=' expr 
     * @param check_redefined 是否检查变量重定义问题
     */
    void parse_assignment_stmt(TokenStream& ts, bool check_redefined = false);
    void parse_list(TokenStream& ts);

private:    /* parse expression */
    void parse_expr(TokenStream& ts);
    void parse_E(TokenStream& ts);
    void parse_term(TokenStream& ts);    
    void parse_T(TokenStream& ts);
    void parse_factor(TokenStream& ts);
    void parse_F(TokenStream& ts);
    void parse_primary(TokenStream& ts);

private:
    VariableTable  _vt;
    header::Number _res;
    bool           _quit;
};

}   // namespace cal
